package com.caowj.composedemo.activity

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.material.Button
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.caowj.composedemo.activity.ui.theme.ComposeDemoTheme

/**
 * 用来演示 组合分层的问题
 * compositionLocalOf()
 * staticCompositionLocalOf()
 *
 * https://blog.csdn.net/Mr_Tony/article/details/118892867
 */
class CompositionLocalActivity : ComponentActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            ComposeDemoTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colors.background
                ) {
                    val text = "我是参数传值"
                    setContent {
//                        body(text)
//                        body2()
                        CompositionLocalDemo()
                    }
                }
            }
        }
    }
}


val ActiveUser =
    compositionLocalOf<String> { error("No active user found!") }//这个需要被定义为可被静态引用的实例或者被@Compose修饰的公共组合中，如果没有提供值的话会报错误


@Composable
private fun body(text: String) {
    CompositionLocalProvider(ActiveUser provides text) {
        Column {
            content()
        }
    }
}


@Composable
private fun body2() {
    //比如在这里定义也是可以的，这样就避免了全局静态变量的那种很糟糕的编码体验，同使也保留了组合隔离的特性
    val text = staticCompositionLocalOf<String> { "我是局部变量" }

    CompositionLocalProvider(ActiveUser provides text.current) {
        Column {
            content()
        }
    }
}

@Composable
private fun content() {
    child()
}

@Composable
private fun child() {//在这里并不需要知道传进来的值，所以可以很方便的保持组件的独立性，当然这个也可以隔好几层，只要在使用前定义就好
    val text = ActiveUser.current
    Text(
        text, textAlign = TextAlign.Center, modifier = Modifier
            .width(150.dp)
            .padding(top = 150.dp)
            .background(color = Color.Magenta)
    )
}

//////////////////////综合示例///////////////////////////

var isStatic = true
var compositionLocalName = ""
val currentLocalColor = if (isStatic) {
    compositionLocalName = "StaticCompositionLocal 场景"
    staticCompositionLocalOf { Color.Black }//刷新CompositionLocalProvider{}内部所有模块
} else {
    compositionLocalName = "DynamicCompositionLocal 场景"
    compositionLocalOf { Color.Black }//仅刷新CompositionLocalProvider{}内部使用到该变量的模块
}

var recomposeFlag = "Init"

@Composable
private fun CompositionLocalDemo() {
    var color by remember { mutableStateOf(Color.Green) }
    Box(
        modifier = Modifier.fillMaxSize(),
        contentAlignment = Alignment.Center
    ) {
        Column(horizontalAlignment = Alignment.CenterHorizontally) {
            Text(text = compositionLocalName)
            Spacer(Modifier.height(20.dp))
            CompositionLocalProvider(
                currentLocalColor provides color
            ) {
                TaggedBox("Wrapper: $recomposeFlag", 400.dp, Color.Red) {
                    TaggedBox("Middle: $recomposeFlag", 300.dp, currentLocalColor.current) {
                        TaggedBox("Inner: $recomposeFlag", 200.dp, Color.Yellow)
                    }
                }
            }
            Spacer(Modifier.height(20.dp))
            Button(
                onClick = {
                    color = Color.Blue
                }
            ) {
                Text(text = "Change middle Theme")
            }
        }
    }
    recomposeFlag = "Recompose"
}

@Composable
private fun TaggedBox(
    tag: String,
    size: Dp,
    background: Color,
    content: @Composable () -> Unit = {}
) {
    Column(
        modifier = Modifier
            .size(size)
            .background(background),
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(text = tag)
        Log.d("caowj", "刷新了$tag")
        Box(
            modifier = Modifier.fillMaxSize(),
            contentAlignment = Alignment.Center
        ) {
            content()
        }
    }
}
